using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Dorm.Helpers;

namespace Dorm.Maps
{
    public class EntityMap<T>: IEntityMap
    {
        public List<MappedProperty> MappedProperties { get; set; }

        public EntityMap()
        {
            MappedProperties = new List<MappedProperty>();
        }

        public MapOption Map(Expression<Func<T, object>> propertyName)
        {
            string strPropertyName = LambdaParser.GetFieldName<T>(propertyName);

            var mappedProperty = new MappedProperty
            {
                PropertyName = strPropertyName,
                PropertyType = typeof(T).GetProperty(strPropertyName).PropertyType,
                MappingType = MappedProperty.MappingTypes.Simple,
            };

            MappedProperties.Add(mappedProperty);

            return new MapOption(mappedProperty);
        }

        public void HasComponent(Expression<Func<T, object>> propertyName)
        {
            string strPropertyName = LambdaParser.GetFieldName<T>(propertyName);

            var mappedProperty = new MappedProperty
            {
                PropertyName = strPropertyName,
                PropertyType = typeof(T).GetProperty(strPropertyName).PropertyType,
                MappingType = MappedProperty.MappingTypes.Component,
            };

            MappedProperties.Add(mappedProperty);
        }

        public CascadeOption References(Expression<Func<T, object>> propertyName)
        {
            string strPropertyName = LambdaParser.GetFieldName<T>(propertyName);

            var mappedProperty = new MappedProperty
            {
                PropertyName = strPropertyName,
                PropertyType = typeof(T).GetProperty(strPropertyName).PropertyType,
                MappingType = MappedProperty.MappingTypes.Reference,
            };

            MappedProperties.Add(mappedProperty);

            return new CascadeOption(mappedProperty);
        }

        public CascadeOption HasMany(Expression<Func<T, object>> propertyName)
        {
            string strPropertyName = LambdaParser.GetFieldName<T>(propertyName);

            var mappedProperty = new MappedProperty
            {
                PropertyName = strPropertyName,
                PropertyType = typeof(T).GetProperty(strPropertyName).PropertyType.GetGenericArguments()[0],
                MappingType = MappedProperty.MappingTypes.HasMany
            };

            MappedProperties.Add(mappedProperty);

            return new CascadeOption(mappedProperty);
        }

        public CascadeOption HasManyToMany(Expression<Func<T, object>> propertyName)
        {
            string strPropertyName = LambdaParser.GetFieldName<T>(propertyName);

            var mappedProperty = new MappedProperty
            {
                PropertyName = strPropertyName,
                PropertyType = typeof(T).GetProperty(strPropertyName).PropertyType.GetGenericArguments()[0],
                MappingType = MappedProperty.MappingTypes.HasManyToMany
            };

            MappedProperties.Add(mappedProperty);

            return new CascadeOption(mappedProperty);
        }
    }
}
